-- Neovim Configuration Module: Definitions of Forms --
VimCommand = function(cmd_str)
	return function() vim.cmd(cmd_str) end
end

ToggleOption = function(opt_name)
	local opt_val = vim.opt[opt_name]:get()
	assert(type(opt_val) == 'boolean', 'option is not boolean')

	vim.opt[opt_name] = not opt_val
end

BindKeys = function(keymap, default_opts)
	default_opts = default_opts or {}
	for _, kbd in ipairs(keymap) do
		vim.keymap.set(kbd[1], kbd[2], kbd[3], vim.tbl_extend('force', default_opts, kbd[4] or {}))
	end
end

HandleIME = function(controller)
	local ime = vim.api.nvim_create_augroup("InputMethod", { clear = true })
	vim.api.nvim_create_autocmd({ "InsertEnter", "InsertLeave" }, {
		desc = "Toggle input method supports with insert mode.",
		group = ime,
		pattern = "*",
		callback = function(t)
			if t.event == "InsertEnter" then controller.on() else controller.off() end
		end,
	})
	vim.api.nvim_create_autocmd({ "CmdlineEnter", "CmdlineLeave" }, {
		desc = "Toggle input method supports with command mode.",
		group = ime,
		pattern = "[/\\?]",
		callback = function(t)
			if t.event == "CmdlineEnter" then controller.on() else controller.off() end
		end,
	})
end

FlattenTable = function(table, prefix, seperator)
	seperator = seperator or '#'
	local new_table = {}
	for key, value in pairs(table) do
		local new_key = prefix and prefix .. seperator .. key or key
		if type(value) == 'table' and not vim.islist(value) then
			local new_value = FlattenTable(value, new_key, seperator)
			for k2, v2 in pairs(new_value) do
				new_table[k2] = v2
			end
		else
			new_table[new_key] = value
		end
	end
	return new_table
end
